package com.sharp.core.raytrace;

import com.sharp.core.math.Vec3;

public class PerspectiveRayFactory extends RayFactory {

	private static class RayInfo {
		float dx, dy;
		float len;
	}
	
	private RayInfo[] rayInfos;
	
	public PerspectiveRayFactory(Camera cam) {
		super(cam);
		Vec3 px = new Vec3();
		Vec3 py = new Vec3();
		Vec3 dir = new Vec3();
		
		rayInfos = new RayInfo[cam.getWidth()*cam.getHeight()];
		for (int x=0; x < cam.getWidth(); ++x) {
			for (int y=0; y < cam.getHeight(); ++y) {
				RayInfo info = new RayInfo();
				info.dx = 2.0f*x/cam.getWidth() - 1;
				info.dy = 2.0f*y/cam.getHeight() - 1;
				px.setTo(getCam().getPlane().getPlaneX());
				px.multiply(info.dx);
				
				py.setTo(getCam().getPlane().getPlaneY());
				py.multiply(info.dy);
				
				dir.setTo(cam.getDir());
				dir.add(px);
				dir.add(py);
				info.len = dir.length();
				
				rayInfos[y*cam.getWidth()+x] = info;
			}
		}
	}

	@Override
	public void cast(Ray ray, int x, int y) {
		RayInfo info = rayInfos[y*getCam().getWidth()+x];
		float dx = info.dx;
		float dy = info.dy;
		
		
		Vec3 px = new Vec3(getCam().getPlane().getPlaneX());
		px.multiply(dx);
		
		Vec3 py = new Vec3(getCam().getPlane().getPlaneY());
		py.multiply(dy);
		
		Vec3 dir = new Vec3(getCam().getDir());
		dir.add(px);
		dir.add(py);
		dir.divide(info.len);
		
		ray.setTo(new Vec3(getCam().getPos()), dir, x, y);
	}

	@Override
	public String toString() {
		return "PerspectiveRayFactory";
	}
}
